package com.antilia.infomaresme;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.antilia.infomaresme.data.dao.interfaces.ICategoriesDao;
import com.antilia.infomaresme.data.dao.interfaces.IItemsDao;
import com.antilia.infomaresme.data.dao.interfaces.IUsersDao;
import com.antilia.infomaresme.data.dataobjects.Category;
import com.antilia.infomaresme.data.dataobjects.CategoryDimension;
import com.antilia.infomaresme.data.dataobjects.Item;
import com.antilia.infomaresme.data.dataobjects.VisibilityStatus;
import com.antilia.infomaresme.data.dataobjects.Language;
import com.antilia.infomaresme.data.dataobjects.User;
import com.antilia.infomaresme.data.dataobjects.UserRole;
import com.antilia.infomaresme.data.dataobjects.UserStatus;
import com.google.inject.Inject;
import com.google.inject.Singleton;

/**
 * 
 * @author Ernesto
 *
 */
@Singleton
public class DataInitialiser {

	public static List<Category> REGIONES;
	
	public static List<Category> CATEGORIES;

	
	@Inject
	public DataInitialiser(IItemsDao iItemsDao, ICategoriesDao categoriesDao, IUsersDao usersDao)
	{
		User user = new User();
		user.setName("Ernesto");
		user.setLastName1("Reinaldo");
		user.setLastName1("Barreiro");
		user.setEmail("reiern70@gmail.com");
		user.setUserId("admin");
		user.setPasword("admin");
		user.setLanguage(Language.en);
		user.setStatus(UserStatus.confirmed);
		user.setUserRole(UserRole.ADMINISTRATOR);
		usersDao.save(user);
		
			
		
		REGIONES = buildCategories(DataInitialiser.class.getResourceAsStream("regiones.xml"), CategoryDimension.geographic);
		
		pesistCategory(REGIONES, null, categoriesDao);
		
		CATEGORIES = buildCategories(DataInitialiser.class.getResourceAsStream("business.xml"), CategoryDimension.business);
		pesistCategory(CATEGORIES, null, categoriesDao);
		//for(Category region : REGIONES) {
			saveCategory(CATEGORIES, new ArrayList<Category>(REGIONES), iItemsDao, user);
		//}
				
	}
	
	protected void pesistCategory(Collection<Category> categories, Category parent, ICategoriesDao categoriesDao) {
		for(Category category: categories) {				
			categoriesDao.save(category);
			if(category.getChildren().size()>0) {
				pesistCategory(category.getChildren(), category, categoriesDao);
			}			
		}
	}
	
	protected void saveCategory(Collection<Category> categories, List<Category> regiones, IItemsDao iItemsDao, User user) {
		for(Category category: categories) 
		{
			if(regiones.size() >0) {
				if(category.getChildren().size() == 0) {
					for(int i = 0; i<50;i++) {
					
						Item item = new Item();
						item.setRating(new Double(Math.random()*5).intValue());
						item.setStatus(i%2==0?VisibilityStatus.visible:VisibilityStatus.hidden);
						item.setCategoryPath(category);
						item.setGeographicPath(regiones.get((int)(Math.random() * regiones.size())));
						item.setTitle(Item.buildTitle(category)+"-Item-"+i);
						item.setDescription(Item.buildTitle(category)+"-Item-"+i);
						item.setPrice(Math.random()*(1000));
						item.setCreationDate(new Date());
						item.setOtherDate(new Date());
						item.setAuthor(user);
						iItemsDao.save(item);	
					}
							
				}
			}
			saveCategory(category.getChildren(), regiones, iItemsDao, user);
		}
	}
	
	public static String readFileAsString(InputStream in) throws java.io.IOException{
        StringBuffer fileData = new StringBuffer(1000);
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }
        reader.close();
        return fileData.toString();
    }
	
	private List<Category> buildCategories(InputStream in, CategoryDimension dimension)  {
		List<Category> categories = null;
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			try {
				Document doc =builder.parse(in);
				NodeList nodes = doc.getElementsByTagName("root");
				for (int i = 0; i < nodes.getLength(); i++) {
				       Element element = (Element) nodes.item(i);
				       categories = parseCategories(null, element, dimension);
				}
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
        return categories;
	}

	private List<Category> parseCategories(Category parent, Element element, CategoryDimension dimension) {
		List<Category> categories = new ArrayList<Category>();
		if(parent == null) {
			NodeList nodes = element.getChildNodes();
			for (int i = 0; i < nodes.getLength(); i++) {
			    if(nodes.item(i) instanceof Element)   {
			    	Element ele = (Element)nodes.item(i);
			    	if(ele.getNodeName().equals("category")) {
			    		Category  category = new Category();
			    		category.setTitle(ele.getAttribute("title"));
			    		category.setDescription(ele.getAttribute("title"));
			    		category.setParent(parent);
			    		category.setDimension(dimension);
			    		categories.add(category);
			    		NodeList nodes1 =  ele.getChildNodes(); 
			    		for(int j = 0; j < nodes1.getLength(); j++) {
			    			if(nodes1.item(j) instanceof Element && (nodes1.item(j).getNodeName().equals("categories"))) {
			    				List<Category> cats = parseCategories(category, (Element)nodes1.item(j), dimension);
			    				for(Category category2: cats) {
			    					category.addCategory(category2);
			    				}
			    			}
			    		}
			    	}
			    }			       
			}
		} else {
			NodeList nodes = element.getChildNodes();
			for (int i = 0; i < nodes.getLength(); i++) {
			    if(nodes.item(i) instanceof Element)   {
			    	Element ele = (Element)nodes.item(i);
			    	if(ele.getNodeName().equals("category")) {
			    		Category  category = new Category();
			    		category.setTitle(ele.getAttribute("title"));
			    		category.setDescription(ele.getAttribute("title"));
			    		category.setParent(parent);
			    		category.setDimension(dimension);
			    		categories.add(category);
			    		NodeList nodes1 =  ele.getChildNodes(); 
			    		for(int j = 0; j < nodes1.getLength(); j++) {
			    			if(nodes1.item(j) instanceof Element && (nodes1.item(j).getNodeName().equals("categories"))) {
			    				List<Category> cats = parseCategories(category, (Element)nodes1.item(j), dimension);
			    				for(Category category2: cats) {
			    					category.addCategory(category2);
			    				}
			    			}
			    		}
			    	}
			    }			       
			}
		}
		return categories;
	}

}
